import { Dispatch } from './Dispatch';
import {
  EventCallback,
  ClearStickyOption,
  EmitResult,
  EventListenerOptions,
  EventBusStats
} from './types/EventTypes';

/**
 * 事件总线类，提供全局事件发布订阅功能
 * 采用单例模式确保全局只有一个实例
 */
export class EventBus {
  // 事件分发器实例
  private readonly dispatch: Dispatch;

  // 单例实例
  private static instance: EventBus;

  // 调试模式开关
  private debugMode: boolean = false;

  // 记录最近触发的事件，用于调试和统计
  private recentEvents: Array<{ name: string; timestamp: number; listenerCount: number }> = [];

  // 最大记录的最近事件数量
  private static MAX_RECENT_EVENTS = 100;

  // 私有构造函数，防止外部实例化
  private constructor() {
    this.dispatch = new Dispatch();
  }

  /**
   * 获取事件总线单例实例
   * @returns 事件总线实例
   */
  public static getInstance(): EventBus {
    if (!EventBus.instance) {
      // 初始化全局容器
      if (!globalThis.__ARKTS_EVENT_BUS__) {
        globalThis.__ARKTS_EVENT_BUS__ = {};
      }

      // 从全局容器获取或创建实例
      if (!globalThis.__ARKTS_EVENT_BUS__.instance) {
        globalThis.__ARKTS_EVENT_BUS__.instance = new EventBus();
      }

      EventBus.instance = globalThis.__ARKTS_EVENT_BUS__.instance;
    }

    return EventBus.instance;
  }

  /**
   * 开启或关闭调试模式
   * @param enabled 是否开启调试模式
   */
  setDebugMode(enabled: boolean): void {
    this.debugMode = enabled;
    if (this.debugMode) {
      console.log('[EventBus] Debug mode enabled');
    }
  }

  /**
   * 订阅事件
   * @param eventName 事件名称
   * @param callback 事件回调函数
   * @param options 订阅选项
   * @returns 监听器ID，用于取消订阅
   */
  on<T extends any[]>(
    eventName: string,
    callback: EventCallback<T>,
    options: EventListenerOptions = {}
  ): number {
    const listenerId = this.dispatch.addListener(
      eventName.toString(),
      callback,
      options
    );

    if (this.debugMode) {
      console.log(`[EventBus] Subscribed to event: ${eventName}, listenerId: ${listenerId}`);
    }

    return listenerId;
  }

  /**
   * 订阅一次性事件（触发一次后自动取消订阅）
   * @param eventName 事件名称
   * @param callback 事件回调函数
   * @param options 订阅选项
   * @returns 监听器ID，用于取消订阅
   */
  once<T extends any[]>(
    eventName: string,
    callback: EventCallback<T>,
    options: Omit<EventListenerOptions, 'once'> = {}
  ): number {
    return this.on(eventName, callback, { ...options, once: true });
  }

  /**
   * 取消订阅事件
   * @param eventName 事件名称
   * @param callback 要取消的回调函数，如果不传则取消该事件的所有订阅
   * @returns 取消的监听器数量
   */
  off<T extends any[]>(
    eventName: string,
    callback?: EventCallback<T>
  ): number {
    const count = this.dispatch.removeListener(
      eventName.toString(),
      callback
    );

    if (this.debugMode && count > 0) {
      console.log(`[EventBus] Unsubscribed from event: ${eventName}, count: ${count}`);
    }

    return count;
  }

  /**
   * 根据监听器ID取消订阅
   * @param eventName 事件名称
   * @param listenerId 监听器ID
   * @returns 是否取消成功
   */
  offById(eventName: string, listenerId: number): boolean {
    const result = this.dispatch.removeListenerById(
      eventName.toString(),
      listenerId
    );

    if (this.debugMode && result) {
      console.log(`[EventBus] Unsubscribed listener ${listenerId} from event: ${eventName}`);
    }

    return result;
  }

  /**
   * 发布事件
   * @param eventName 事件名称
   * @param args 事件参数
   * @returns 事件发布结果
   */
  async emit<T extends any[]>(
    eventName: string,
    ...args: T
  ): Promise<EmitResult> {
    if (this.debugMode) {
      console.log(`[EventBus] Emitting event: ${eventName}, args:`, JSON.stringify(args));
    }

    const result = await this.dispatch.emit(eventName.toString(), ...args);

    // 记录事件触发信息，用于统计和调试
    this.recentEvents.push({
      name: eventName.toString(),
      timestamp: Date.now(),
      listenerCount: result.listenerCount
    });

    // 保持最近事件列表的大小
    if (this.recentEvents.length > EventBus.MAX_RECENT_EVENTS) {
      this.recentEvents.shift();
    }

    if (this.debugMode) {
      console.log(`[EventBus] Emitted event: ${eventName}, result:`, JSON.stringify(result));
    }

    if (result.errorCount > 0) {
      console.error(`[EventBus] Errors occurred while emitting ${eventName}:`, result.errors);
    }

    return result;
  }

  /**
   * 清理粘性事件
   * @param option 清理选项
   */
  clearStickyEvents(option: ClearStickyOption = {}): void {
    this.dispatch.clearStickyEvents(option);

    if (this.debugMode) {
      console.log(`[EventBus] Cleared sticky events:`, option);
    }
  }

  /**
   * 获取事件的监听器数量
   * @param eventName 事件名称
   * @returns 监听器数量
   */
  getListenerCount(eventName: string): number {
    return this.dispatch.getListenerCount(eventName.toString());
  }

  /**
   * 检查事件是否有监听器
   * @param eventName 事件名称
   * @returns 如果有监听器则返回true，否则返回false
   */
  hasListeners(eventName: string): boolean {
    return this.dispatch.hasListeners(eventName.toString());
  }

  /**
   * 获取所有已注册的事件名称
   * @returns 事件名称数组
   */
  getEventNames(): string[] {
    return this.dispatch.getEventNames();
  }

  /**
   * 清空所有事件和监听器
   * 主要用于测试场景或应用退出前清理
   */
  clearAll(): void {
    this.dispatch.clearAll();
    this.recentEvents = [];

    if (this.debugMode) {
      console.log(`[EventBus] Cleared all events and listeners`);
    }
  }

  /**
   * 获取事件总线统计信息
   * @returns 统计信息对象
   */
  getStats(): EventBusStats {
    const eventNames = this.getEventNames();
    let listenerCount = 0;

    eventNames.forEach(name => {
      listenerCount += this.getListenerCount(name);
    });

    return {
      eventCount: eventNames.length,
      listenerCount,
      stickyEventCount: this.dispatch.getEventNames().filter(name =>
      this.getListenerCount(name) > 0 &&
        // 简化判断，实际可能需要更精确的粘性事件计数
        this.dispatch.getListenerCount(name) > 0
      ).length,
      recentEvents: [...this.recentEvents]
    };
  }

  /**
   * 打印事件总线状态信息（调试用）
   */
  printStats(): void {
    const stats = this.getStats();
    console.log('[EventBus] Current stats:', JSON.stringify({
      eventCount: stats.eventCount,
      listenerCount: stats.listenerCount,
      stickyEventCount: stats.stickyEventCount,
      recentEventCount: stats.recentEvents.length
    }));
  }
}

// 导出便捷实例，方便直接使用
export const eventBus = EventBus.getInstance();
